#include "ostree-repo-static-delta-private.h"
#include "ostree-metalink.h"
#include "otutil.h"
+#include "ot-fs-utils.h"
#include <gio/gunixinputstream.h>
progress, cancellable, error);
}
+gboolean
+_ostree_repo_load_cache_summary_if_same_sig (OstreeRepo *self,
+ const char *remote,
+ GBytes *summary_sig,
+ GBytes **summary,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ const char *summary_cache_sig_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_PATH, "/", remote, ".sig");
+
+ glnx_fd_close int prev_fd = -1;
+ g_autoptr(GBytes) old_sig_contents = NULL;
+
+ if (!ot_openat_ignore_enoent (self->repo_dir_fd, summary_cache_sig_file, &prev_fd, error))
+ goto out;
+
+ if (prev_fd < 0)
+ {
+ ret = TRUE;
+ goto out;
+ }
+
+ old_sig_contents = glnx_fd_readall_bytes (prev_fd, cancellable, error);
+ if (!old_sig_contents)
+ goto out;
+
+ if (g_bytes_compare (old_sig_contents, summary_sig) == 0)
+ {
+ const char *summary_cache_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_PATH, "/", remote);
+ glnx_fd_close int summary_fd = -1;
+ GBytes *summary_data;
+
+
+ summary_fd = openat (self->repo_dir_fd, summary_cache_file, O_CLOEXEC | O_RDONLY);
+ if (summary_fd < 0)
+ {
+ if (errno == ENOENT)
+ {
+ (void) unlinkat (self->repo_dir_fd, summary_cache_sig_file, 0);
+ ret = TRUE;
+ goto out;
+ }
+
+ glnx_set_error_from_errno (error);
+ goto out;
+ }
+
+ summary_data = glnx_fd_readall_bytes (summary_fd, cancellable, error);
+ if (!summary_data)
+ goto out;
+ *summary = summary_data;
+ }
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+gboolean
+_ostree_repo_cache_summary (OstreeRepo *self,
+ const char *remote,
+ GBytes *summary,
+ GBytes *summary_sig,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ const char *summary_cache_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_PATH, "/", remote);
+ const char *summary_cache_sig_file = glnx_strjoina (_OSTREE_SUMMARY_CACHE_PATH, "/", remote, ".sig");
+
+ if (!glnx_shutil_mkdir_p_at (self->repo_dir_fd, _OSTREE_SUMMARY_CACHE_PATH, 0775, cancellable, error))
+ goto out;
+
+ if (!glnx_file_replace_contents_at (self->repo_dir_fd,
+ summary_cache_file,
+ g_bytes_get_data (summary, NULL),
+ g_bytes_get_size (summary),
+ self->disable_fsync ? GLNX_FILE_REPLACE_NODATASYNC : GLNX_FILE_REPLACE_DATASYNC_NEW,
+ cancellable, error))
+ goto out;
+
+ if (!glnx_file_replace_contents_at (self->repo_dir_fd,
+ summary_cache_sig_file,
+ g_bytes_get_data (summary_sig, NULL),
+ g_bytes_get_size (summary_sig),
+ self->disable_fsync ? GLNX_FILE_REPLACE_NODATASYNC : GLNX_FILE_REPLACE_DATASYNC_NEW,
+ cancellable, error))
+ goto out;
+
+ ret = TRUE;
+ out:
+ return ret;
+
+}
+
/* Documented in ostree-repo.c */
gboolean
ostree_repo_pull_with_options (OstreeRepo *self,
g_autoptr(GVariant) refs = NULL;
g_autoptr(GVariant) deltas = NULL;
g_autoptr(GVariant) additional_metadata = NULL;
-
- if (!pull_data->summary)
+ gboolean summary_from_cache = FALSE;
+
+ if (!pull_data->summary_data_sig)
+ {
+ uri = suburi_new (pull_data->base_uri, "summary.sig", NULL);
+ if (!fetch_uri_contents_membuf_sync (pull_data, uri, FALSE, TRUE,
+ &bytes_sig, cancellable, error))
+ goto out;
+ soup_uri_free (uri);
+ }
+
+ if (bytes_sig && !_ostree_repo_load_cache_summary_if_same_sig (self,
+ remote_name_or_baseurl,
+ bytes_sig,
+ &bytes_summary,
+ cancellable,
+ error))
+ goto out;
+
+ if (bytes_summary)
+ summary_from_cache = TRUE;
+
+ if (!pull_data->summary && !bytes_summary)
{
uri = suburi_new (pull_data->base_uri, "summary", NULL);
if (!fetch_uri_contents_membuf_sync (pull_data, uri, FALSE, TRUE,
&bytes_summary, cancellable, error))
goto out;
soup_uri_free (uri);
- }
+ }
if (!bytes_summary && pull_data->gpg_verify_summary)
{
goto out;
}
- if (bytes_summary)
- {
- uri = suburi_new (pull_data->base_uri, "summary.sig", NULL);
- if (!fetch_uri_contents_membuf_sync (pull_data, uri, FALSE, TRUE,
- &bytes_sig, cancellable, error))
- goto out;
- soup_uri_free (uri);
- }
-
if (!bytes_sig && pull_data->gpg_verify_summary)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
pull_data->summary_data_sig = g_bytes_ref (bytes_sig);
}
+
+ if (!summary_from_cache && bytes_summary && bytes_sig)
+ {
+ if (!_ostree_repo_cache_summary (self,
+ remote_name_or_baseurl,
+ bytes_summary,
+ bytes_sig,
+ cancellable,
+ error))
+ goto out;
+ }
+
if (pull_data->gpg_verify_summary && bytes_summary && bytes_sig)
{
g_autoptr(GVariant) sig_variant = NULL;